package vg.modules.search;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import vg.services.data_base_manager.data.header.AttributeHeader;
import vg.services.data_base_manager.interfaces.IModel;
import vg.services.data_base_manager.realization.DataBaseFields;
import vg.services.main_manager.MainManager;
import vg.services.user_interface_manager.additional_swing_components.conditionPanel.data.AConditionData;
import vg.services.user_interface_manager.additional_swing_components.conditionPanel.data.ConditionalPanelData;
import vg.services.user_interface_manager.additional_swing_components.conditionPanel.data.GeneralConditionData;

/**
 * This class works with database and so has dependency code.
 * If structure of database in project Visual Graph will changes that 
 * developers must change requests in this class.
 * @author tzolotuhin
 */
public class DataBaseWorker4Search {
	public static Set<Integer> get_vertex_ids(ConditionalPanelData data, IModel model, int graphModelId) {
		if(data == null || model == null) return null;

		// build request
		String request = "SELECT distinct v.id " +
						 "FROM " + DataBaseFields.GRAPH_TABLE + " g," +
						 		   DataBaseFields.VERTEX_TABLE + " v " +
						 "WHERE " + "g." + DataBaseFields.GRAPH_TABLE_MODEL_ID + "=" + graphModelId + " and " +
						 		    "v." + DataBaseFields.VERTEX_TABLE_GRAPH_ID + "=" + "g." + DataBaseFields.GRAPH_TABLE_ID;
						 		  
		if(data.conditions.size() > 0)
			request += " and ( ";
		int i = 0;
		for(AConditionData buf : data.conditions) {
			request += " v." + DataBaseFields.VERTEX_TABLE_ID + " in (" + 
					   " SELECT a." + DataBaseFields.ATTRIBUTE_TABLE_OWNER_ID + 
					   " FROM " + DataBaseFields.ATTRIBUTE_TABLE + " a " + 
					   " WHERE " + "a." + DataBaseFields.ATTRIBUTE_TABLE_OWNER_TYPE + "=" + AttributeHeader.DEF_VERTEX_OWNER_TYPE + " and " + 
					   			   "a." + DataBaseFields.ATTRIBUTE_TABLE_OWNER_ID + "=v." + DataBaseFields.VERTEX_TABLE_ID + " and " +
					   			   "a." + DataBaseFields.ATTRIBUTE_TABLE_NAME + "='";
			switch (buf.type) {
				case AConditionData.DEF_GENERAL_CONDITION:
				default: {
					GeneralConditionData gen_cond = (GeneralConditionData)buf;
					request += gen_cond.name + "' and a." + DataBaseFields.ATTRIBUTE_TABLE_VALUE + " LIKE '%" + gen_cond.value + "%') ";
				}
			}
			
			if(i < data.operators.size()) {
				request += data.operators.get(i).operator;
			}
			i++;
		}
		
		if(data.conditions.size() > 0)
			request += ");";
		else
			request += "; ";

		// execute request
		List<List<Object>> result = model.executeSQLRequest(request.toString());
		if (result != null) {
			Set<Integer> result_vertex = new HashSet<Integer>();
			for (List<Object> row : result) {
				Integer id = (Integer) row.get(0);
				result_vertex.add(id);
			}
			return (result_vertex);
		} else {
			MainManager.windowMessage.errorMessage("Can't execute SQL request.", "Filter panel error");
			return null;
		}
	}
	
	public static Map<String, Set<String>> get_general_attributes4vertex(Set<Integer> vertex_ids, IModel model) {
		if(vertex_ids == null || model == null) return null;
		
		// build request
		Map<String, Set<String>> result = new HashMap<String, Set<String>>();
		StringBuilder request = new StringBuilder(4*1024);		
		for(Integer buf_id : vertex_ids) {
			request.setLength(0);
			request.append("SELECT * FROM " + DataBaseFields.ATTRIBUTE_TABLE + " a " + " WHERE " + "a." + DataBaseFields.ATTRIBUTE_TABLE_OWNER_TYPE + "=");
			request.append(AttributeHeader.DEF_VERTEX_OWNER_TYPE);
			request.append(" and a." + DataBaseFields.ATTRIBUTE_TABLE_ID + "=");
			request.append(buf_id);
			request.append(";");
			
			List<List<Object>> re_request = model.executeSQLRequest(request.toString());
			if (result != null) {
				for (List<Object> row : re_request) {
					String name = (String)row.get(3);
					String value = (String)row.get(4);
					
					Set<String> values = result.get(name);
					if (values != null) {
						if (!values.contains(value)) {
							values.add(value);
						}
					} else {
						values = new HashSet<String>();
						values.add(value);
						result.put(name, values);
					}
				}
			}
		}
		
		return result;
	}
}
